package com.aphrodite.ui.widgets.barcode;

import java.util.Hashtable;
import java.util.Vector;

final class PostNetBarcode extends LinearBarcode {
	static final class ModuleTemplate {
		private static final Vector KEYS = new Vector();

		private static final Hashtable SET = new Hashtable();
		public static final PostNetModule START_STOP = new PostNetModule(new int[] { 1 });

		static {
			initBaseSet();
		}

		static int getIndex(String key) {
			return KEYS.indexOf(key);
		}

		static Module getModule(String key) {
			PostNetModule module = null;
			module = (PostNetModule) SET.get(key);
			module.setSymbol(key);
			return module;
		}

		static Module getModuleForIndex(int index) {
			return getModule((String) KEYS.elementAt(index));
		}

		private static void initBaseSet() {
			KEYS.addElement("0");
			SET.put("0", new PostNetModule(new int[] { 1, 1, 0, 0, 0 }));
			KEYS.addElement("1");
			SET.put("1", new PostNetModule(new int[] { 0, 0, 0, 1, 1 }));
			KEYS.addElement("2");
			SET.put("2", new PostNetModule(new int[] { 0, 0, 1, 0, 1 }));
			KEYS.addElement("3");
			SET.put("3", new PostNetModule(new int[] { 0, 0, 1, 1, 0 }));
			KEYS.addElement("4");
			SET.put("4", new PostNetModule(new int[] { 0, 1, 0, 0, 1 }));
			KEYS.addElement("5");
			SET.put("5", new PostNetModule(new int[] { 0, 1, 0, 1, 0 }));
			KEYS.addElement("6");
			SET.put("6", new PostNetModule(new int[] { 0, 1, 1, 0, 0 }));
			KEYS.addElement("7");
			SET.put("7", new PostNetModule(new int[] { 1, 0, 0, 0, 1 }));
			KEYS.addElement("8");
			SET.put("8", new PostNetModule(new int[] { 1, 0, 0, 1, 0 }));
			KEYS.addElement("9");
			SET.put("9", new PostNetModule(new int[] { 1, 0, 1, 0, 0 }));
		}

	}

	private static final class PostNetModule extends Module {

		protected final static double BARWIDTH = 3.0;
		protected final static double BLANKWIDTH = 4.0;

		PostNetModule(int[] bars) {
			super(bars);
		}

		protected double draw(AbstractOutput output, double x, double y) throws OutputException {
			double sum = 0;
			double fullheight = HEIGHT;
			double halfheight = fullheight * .4;

			for (int i = 0; i < bars.length; i++) {
				int bar = bars[i];
				if (bar == 0) {
					output.drawBar((int) x, (int) (y + (fullheight - halfheight)), (int) BARWIDTH, (int) halfheight,
							true);
				} else {
					output.drawBar((int) x, (int) y, (int) BARWIDTH, (int) fullheight, true);
				}
				sum += BARWIDTH;
				x += BARWIDTH;
				output.drawBar((int) x, (int) y, (int) BLANKWIDTH, (int) fullheight, false);
				sum += BLANKWIDTH;
				x += BLANKWIDTH;
				output.drawBar((int) x, (int) y, (int) BLANKWIDTH, (int) fullheight, false);
			}
			return sum;
		}
	}

	protected static int HEIGHT = 20;

	static boolean isValid(String key) {
		return ModuleTemplate.KEYS.contains(key);
	}

	PostNetBarcode(String zipcode, int height) throws BarcodeException {
		super(zipcode, height);
		HEIGHT = height;
	}

	// PostNetBarcode(String zipcode) throws BarcodeException {
	// this(zipcode, 20);
	// }

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.sourceforge.barbecue.Barcode#calculateChecksum()
	 */
	protected Module calculateChecksum() {
		return null;
	}

	public void cleanUp() {
	// TODO Auto-generated method stub

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.sourceforge.barbecue.Barcode#encodeData()
	 */
	protected Module[] encodeData() {
		long sum = 0;
		Vector modules = new Vector();
		for (int i = 0; i < data.length(); i++) {
			String c = String.valueOf(data.charAt(i));
			Module module = ModuleTemplate.getModule(c);
			sum += Long.parseLong(c);
			modules.addElement(module);
		}

		// add the check digit
		long check = (10 - (sum % 10));
		if (check == 10) {
			check = 0;
		}

		modules.addElement(ModuleTemplate.getModule(String.valueOf(check)));
		Module[] ret = new Module[modules.size()];
		modules.copyInto(ret);
		return ret;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.sourceforge.barbecue.Barcode#getBarcodeWidth(int)
	 */
	protected double getBarcodeWidth(int resolution) {
		return 0;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.sourceforge.barbecue.Barcode#getPostAmble()
	 */
	protected Module getPostAmble() {
		return ModuleTemplate.START_STOP;
	}

	// /*
	// * (non-Javadoc)
	// *
	// * @see java.awt.Component#getHeight()
	// */
	// public int getHeight() {
	// return HEIGHT;
	// }

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.sourceforge.barbecue.Barcode#getPreAmble()
	 */
	protected Module getPreAmble() {
		return ModuleTemplate.START_STOP;
	}

}
